{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# GA-LMS standard (Matlab)\n",
    "\n",
    "This is an example on how to run the GA-LMS (standard) binary from Matlab.\n",
    "\n",
    "You can use this notebook as a simple instruction guide (plain text) to understand the script before running it from your Matlab version. If you want to actually run the notebook with the Matlab kernel, you should:\n",
    "1 - Have Matlab installed, and;\n",
    "2 - Follow the instructions on <a href=\"http://anneurai.net/2015/11/12/matlab-based-ipython-notebooks/\">http://anneurai.net/2015/11/12/matlab-based-ipython-notebooks/</a> to make the Jupyter notebook capable of running the Matlab kernel.\n",
    "\n",
    "In this example, the multivectors samples belong to the Geometric Algebra of $\\mathbb{R}^3$. Thus, each regressor and weight vector entry has 8 coefficients, i.e., for each entry of the weight vector, 8 coefficients have to be estimated. This constrasts with the usal LMS which only estimates real/complex entries. For further information, please refer to the GA documentation at <a href=\"http://www.openga.org\">www.openga.org</a>.  \n",
    "\n",
    "The user is able to set the following AF parameters:\n",
    "\n",
    "<p>Number of filter taps:      M</p><p>Time iterations:            N</p><p>Realizations:               L</p><p>AF step size:               mu</p><p>Measurement Noise variance: sigma2v</p>      \n",
    "\n",
    "At the end, the learning curves for the Mean-Square Error (MSE) and the Excess Mean-Square Error (EMSE) are plotted and saved (in .fig and .pdf) together with simulation data (simData.mat)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "% gaafs.m - General script to call the GAAFs \n",
    "% \n",
    "% Supplementary material for IEEE Signal Processing Transactions \n",
    "% submission:\n",
    "% \"Geometric Algebra Adaptive Filters\", \n",
    "% Authors: Wilder Lopes (wilder@usp.br), Cassio Lopes (cassio@lps.usp.br)\n",
    "%\n",
    "% Matlab code by:\n",
    "% Wilder Bezerra Lopes - Ph.D. Student \n",
    "% University of Sao Paulo (USP)\n",
    "% February 2016\n",
    "% www.lps.usp.br/wilder\n",
    "% wilderlopes@gmail.com\n",
    "%\n",
    "% The MIT License (MIT)\n",
    "% \n",
    "% Copyright (c) 2016 onwards, by Wilder Lopes\n",
    "% \n",
    "% Permission is hereby granted, free of charge, to any person obtaining a copy\n",
    "% of this software and associated documentation files (the \"Software\"), to deal\n",
    "% in the Software without restriction, including without limitation the rights\n",
    "% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n",
    "% copies of the Software, and to permit persons to whom the Software is\n",
    "% furnished to do so, subject to the following conditions:\n",
    "% \n",
    "% The above copyright notice and this permission notice shall be included in\n",
    "% all copies or substantial portions of the Software.\n",
    "% \n",
    "% THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n",
    "% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n",
    "% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n",
    "% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n",
    "% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n",
    "% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n",
    "% THE SOFTWARE."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Please point the variable 'user_folder' (below) to the path where the filter codes are stored. In my case, the path is '/home/wilder/Documents/Doctorate/gaaf_cpp.git'\n",
    "\n",
    "Also, variable 'GA_LMS_Cpp' should point to the binary generated after compiling the C++ code."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "close all\n",
    "clear, clc\n",
    "\n",
    "%============= Type in the path for the extracted folder ==================\n",
    "user_folder = '/home/wilder/Documents/Doctorate/gaaf_cpp.git';\n",
    "%==========================================================================\n",
    "\n",
    "GA_LMS_Cpp = [user_folder,'/GA-LMS/build/GA-LMS']; %Note which binary is selected!!!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Define values of simulation parameters. If you wish to run parametric simulations, you can set several values\n",
    "in an array. For example, if you want to test the behavior of the GA-LMS for several number of taps, say {5,10,15},\n",
    "you should define M = [5 10 15]. The same is valid for the step size 'mu' and the noise variance 'sigma2v'. The results are stored in separate folders at the end of the simulation. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "% Simulation parameters\n",
    "M            = 10; % System order (number of taps)\n",
    "N            = 3000; % Time iterations\n",
    "L            = 100; % Amount of experiments/realizations;\n",
    "mu           = 0.005; % AF Step size\n",
    "sigma2v      = 1e-4; % Variance of measurement noise\n",
    "\n",
    "\n",
    "MSE_steadyState         = zeros(length(M),1); % To accumulate the average steady-state MSE\n",
    "EMSE_steadyState        = zeros(length(M),1); % To accumulate the average steady-state EMSE\n",
    "MSE_steadyState_theory  = zeros(length(M),1); % To accumulate the theoretical steady-state MSE\n",
    "EMSE_steadyState_theory = zeros(length(M),1); % To accumulate the theoretical steady-state EMSE\n",
    "MSE_minus_theory        = zeros(length(M),1); % To accumulate the average steady-state \n",
    "                                              % MSE minus EMSE theory\n",
    "EMSE_minus_theory       = zeros(length(M),1); % To accumulate the average steady-state \n",
    "                                              % EMSE minus EMSE theory"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Starting loops:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "for j=1:length(sigma2v) % Measurement Noise loop\n",
    "\n",
    "    M_counter = 0;\n",
    "    \n",
    "for order=M % Filter taps loop\n",
    "    \n",
    "    M_counter = M_counter + 1; % Counting how many different M orders are\n",
    "                               % being used.\n",
    "    if order > 40 % If number of taps is higher than 40, increase the \n",
    "                  % the number of iterations so the steady-state level can\n",
    "                  % be calculated by averaging the last 200 points.\n",
    "        N = 6000;\n",
    "    end\n",
    "\n",
    "\n",
    "for i=1:length(mu) % Step size loop\n",
    "    display(sprintf('Running GA-LMS: sigma^2 = %g (%g/%g) | mu = %g (%g/%g)',...\n",
    "        sigma2v(j), j, length(sigma2v), mu(i), i, length(mu)));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now the Matlab script assembles the command to call the GA-LMS binary. This was tested in Ubuntu-Linux 14.04 LTS. In case the follwoing does not work out-of-the-box for you, please adapt it accordingly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "% Calling the GA-LMS binary (compiled from C++ code). The system function\n",
    "% argument has to be a string. See the following answer for more\n",
    "% information:\n",
    "% http://www.mathworks.com/matlabcentral/answers/92537-how-do-i-pass-arguments-into-and-out-of-my-standalone-executable.\n",
    "cmd = [GA_LMS_Cpp,' ',num2str(order),' ',num2str(L),' ',num2str(N),' ', ...\n",
    "    num2str(mu(i)),' ',num2str(sigma2v(j))];\n",
    "\n",
    "system(cmd); % executes the binary"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And then imports the results provided by the simulation (it imports txt files into Matlab variables):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "% Importing results gernearted by the C++ code into Matlab \n",
    "import_MSE;\n",
    "import_EMSE;\n",
    "import_MSE_theory;\n",
    "import_EMSE_theory;\n",
    "import_W; % Imports final multivector W (weight vector)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Generating variables to be plotted:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "mean_MSE  = mean(MSE((N-200):N));\n",
    "mean_EMSE = mean(EMSE((N-200):N));\n",
    "\n",
    "MSE_steadyState(M_counter,:)         = 10*log10(mean_MSE); % Averaging the MSE last 200 points\n",
    "EMSE_steadyState(M_counter,:)        = 10*log10(mean_EMSE); % Averaging the EMSE last 200 points\n",
    "MSE_steadyState_theory(M_counter,:)  = 10*log10(MSE_theory); % Steady-state theory for each M\n",
    "EMSE_steadyState_theory(M_counter,:) = 10*log10(EMSE_theory); % Steady-state theory for each M\n",
    "MSE_minus_theory(M_counter,:)        = 10*log10(mean_MSE - MSE_theory); % Steady-state MSE minus MSE bound\n",
    "EMSE_minus_theory(M_counter,:)       = 10*log10(mean_EMSE - EMSE_theory); % Steady-state EMSE minus EMSE bound\n",
    "\n",
    "MSE              = 10*log10(MSE);\n",
    "EMSE             = 10*log10(EMSE);\n",
    "MSE_theory_line  = 10*log10(MSE_theory*ones(N,1));\n",
    "EMSE_theory_line = 10*log10(EMSE_theory*ones(N,1));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Creating directories for saving simulation data. The folder structure is\n",
    "Results ---> sigma2v ---> M ---> N ---> L ---> mu:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%============================== SAVING ====================================\n",
    "dataFolder = strsplit(pwd, '/'); % getting the folder name where the data is.\n",
    "filename_to_save = strcat('simData','.mat'); % file name to save.\n",
    "savefolder = fullfile(pwd,'Results',sprintf('sigma2v = %g',sigma2v(j)), ...\n",
    "            sprintf('M=%g',order), sprintf('N=%g',N),sprintf('L=%g',L), ...\n",
    "            sprintf('mu = %g',mu(i)));\n",
    "    \n",
    "mkdir(savefolder);\n",
    "\n",
    "save(fullfile(savefolder,filename_to_save));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "MSE and EMSE figures are created, plotted and saved in both .fig and .pdf:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%============================= PLOTTING ===================================\n",
    "iterations = length(MSE);\n",
    "dataSet = strcat(strjoin(strsplit(strcat(strjoin(dataFolder(end))),'_'))); % grabing the name of the data set\n",
    "\n",
    "% fig_width = 5;\n",
    "% fig_height = 2.3;\n",
    "\n",
    "% Sizes for IEEE paper\n",
    "fig_width = 10;\n",
    "fig_height = 3.6;\n",
    "\n",
    "line_width = 3;\n",
    "\n",
    "MSE_figure = figure('Name','MSE',...\n",
    "                    'Units','inches',...\n",
    "                    'Position',[0 0 fig_width fig_height],...\n",
    "                    'PaperPositionMode','auto',...\n",
    "                    'Visible','off'); \n",
    "title(sprintf('GA-LMS - M=%g, N=%g, L=%g, mu=%g, sigma2v=%g',order,N,L,mu(i),sigma2v(j)),...\n",
    "    'FontUnits','points','FontWeight','normal','FontSize',12,'FontName','Times'),\n",
    "xlabel('Iterations','Interpreter','latex','FontUnits','points','FontSize',18,'FontName','Times'), \n",
    "ylabel('MSE (dB)','interpreter','latex','FontUnits','points','FontSize',18,'FontName','Times'), hold on\n",
    "plot((0:iterations-1),MSE,'b-','LineWidth',1.5);\n",
    "plot((0:iterations-1),MSE_theory_line,'magenta--','LineWidth',3);\n",
    "grid on;\n",
    "% annotation('textarrow',[0.23,0.30],[0.40,0.63],...\n",
    "% 'String','$\\sigma^2_v = 10^{{}^{\\_}7}$','FontSize',font_size,'FontName','Times','Interpreter','latex');\n",
    "legend('MSE','MSE bound'); legend boxoff;\n",
    "set(gcf,'PaperPositionMode','Auto','PaperUnits','Inches','PaperSize',[fig_width, fig_height+0.1]);\n",
    "set(gca,'FontUnits','points','FontWeight','normal','FontSize',14,'FontName','Times');\n",
    "%savefig(fullfile(savefolder,'Figure_MSE.fig')) % For Matlab 2014a\n",
    "saveas(MSE_figure,fullfile(savefolder,'Figure_MSE.fig'));\n",
    "legend 'off';\n",
    "title '';\n",
    "print('-dpdf','-r300',fullfile(savefolder,'Figure_MSE'))\n",
    "\n",
    "\n",
    "EMSE_figure = figure('Name','EMSE',...\n",
    "                    'Units','inches',...\n",
    "                    'Position',[0 0 fig_width fig_height],...\n",
    "                    'PaperPositionMode','auto',...\n",
    "                    'Visible','off');\n",
    "title(sprintf('GA-LMS - M=%g, N=%g, L=%g, mu=%g, sigma2v=%g',order,N,L,mu(i),sigma2v(j)),...\n",
    "    'FontUnits','points','FontWeight','normal','FontSize',12,'FontName','Times','Interpreter','latex'),\n",
    "xlabel('Iterations','Interpreter','latex','FontUnits','points','FontSize',18,'FontName','Times'), \n",
    "ylabel('EMSE (dB)','interpreter','latex','FontUnits','points','FontSize',18,'FontName','Times'), hold on\n",
    "plot((0:iterations-1),EMSE,'r-','LineWidth',1.5);\n",
    "plot((0:iterations-1),EMSE_theory_line,'magenta--','LineWidth',3);\n",
    "grid on;\n",
    "legend('EMSE','EMSE bound'); legend boxoff;\n",
    "set(gcf,'PaperPositionMode','Auto','PaperUnits','Inches','PaperSize',[fig_width, fig_height+0.1]);\n",
    "set(gca,'FontUnits','points','FontWeight','normal','FontSize',14,'FontName','Times');\n",
    "%savefig(fullfile(savefolder,'Figure_EMSE.fig'))  % For Matlab 2014a\n",
    "saveas(EMSE_figure,fullfile(savefolder,'Figure_EMSE.fig'));\n",
    "legend 'off';\n",
    "title '';\n",
    "print('-dpdf','-r300',fullfile(savefolder,'Figure_EMSE'))\n",
    "\n",
    "end\n",
    "\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When performing parametric simulations varying the system order/filter taps (M), an extra figure is generated and saved. It shows the steady-state MSE and EMSE (both theoretical and simulated) as a function of M: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "MSE_and_EMSE_figure = figure('Name','EMSE_and_MSE',...\n",
    "                    'Units','inches',...\n",
    "                    'Position',[0 0 fig_width fig_height],...\n",
    "                    'PaperPositionMode','auto',...\n",
    "                    'Visible','off');\n",
    "title(sprintf('GAAF - Multivector Entry - Average Steady-State Error - mu = %g, sigma2v = %g', mu(i), sigma2v(j)),...\n",
    "    'FontUnits','points','FontWeight','normal','FontSize',12,'FontName','Times','Interpreter','latex'),\n",
    "xlabel('System Order (Taps)','Interpreter','latex','FontUnits','points','FontSize',18,'FontName','Times'), \n",
    "ylabel('Error (dB)','interpreter','latex','FontUnits','points','FontSize',18,'FontName','Times'), hold on\n",
    "plot(M,MSE_steadyState,'b--o','LineWidth',3,'MarkerSize',10);\n",
    "plot(M,EMSE_steadyState,'r--o','LineWidth',3,'MarkerSize',10);\n",
    "plot(M,MSE_steadyState_theory,'green-*','LineWidth',2,'MarkerSize',10);\n",
    "plot(M,EMSE_steadyState_theory,'magenta-*','LineWidth',2,'MarkerSize',10);\n",
    "grid on;\n",
    "legend('MSE','EMSE','MSEtheory','EMSEtheory'); legend boxoff;\n",
    "set(gcf,'PaperPositionMode','Auto','PaperUnits','Inches','PaperSize',[fig_width, fig_height+0.1]);\n",
    "set(gca,'FontUnits','points','FontWeight','normal','FontSize',14,'FontName','Times');\n",
    "%savefig(fullfile(savefolder,'Figure_MSE_and_EMSE.fig'))  % For Matlab 2014a\n",
    "saveas(MSE_and_EMSE_figure,fullfile(savefolder,'Figure_MSE_and_EMSE.fig'));\n",
    "print('-dpdf','-r300',fullfile(savefolder,'Figure_MSE_and_EMSE'))\n",
    "\n",
    "end\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You should have a new folder 'Results' in your directory. Open it and navigate to the corner (case of parametric simulation) you want to see. Note that the figures are not visible by default (to avoid several of them accumulating in your screen). To open them you should type the following command in Matlab (from the folder of interest):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "openfig('MSE_figure.fig','visible') % Example on how to visualize the saved 'MSE_figure.fig' \n",
    "                                    % figure after the end of the simulation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Of course, you can always access the figures in pdf as well. Just click on the pdf file stored in the same result folder."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Matlab",
   "language": "matlab",
   "name": "matlab"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
